#ifndef TBB_H
#define TBB_H

#include <vector>
#include <set>
#include <utility>
#include <cstdint>
#include <stdexcept>
#include <functional>
#include <type_traits>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#include <map>
#include "../MEMREF.h"


class SBB;
typedef std::map<std::string, std::vector<SBB> *> UMAP;
void compute(const std::string &threadname, UMAP &threadToSBB, uint32_t i);
void ComputeVectorClocks(UMAP &);

class SBB {
  public:
	typedef std::vector<MA> Container;
	typedef Container::iterator iterator;
	typedef Container::const_iterator const_iterator;
	typedef std::pair<std::string, uint32_t> P;
	// Constructor
	SBB(std::ifstream &infile);

	bool IsRecv() const { return !recv_.empty(); }
	bool IsLast() const { return end_; }
	bool IsLocked() const { return locked_; }

	// Coalesce overlapping intervals.
	// Write mode interval overides read mode interval.
	void Coalesce(int stage = 1);

	//Forwarders.
	size_t size() const { return ma_container_.size(); }
	bool empty() const { return ma_container_.empty(); }
	const_iterator begin() const { return ma_container_.begin(); }
	iterator begin() { return ma_container_.begin(); }
	const_iterator end() const { return ma_container_.end(); }
	MA &operator[] (size_t i) { return ma_container_[i]; }
	const MA &operator[] (size_t i) const { return ma_container_[i]; }
	iterator end() { return ma_container_.end(); }

  private:
	bool end_;
	bool locked_;
	std::vector<P> recv_;
	std::unordered_map<std::string, std::pair<uint32_t, uint32_t>> clocks_pred_;
	Container ma_container_;
	friend void compute(const std::string &threadname, UMAP &threadToSBB, uint32_t i);
};


std::ostream &operator<<(std::ostream &os, const SBB &sbb);

//Complexity: O(nlogn).
typedef std::pair<size_t, size_t> RACEPAIR;
RACEPAIR DRCheck(SBB const &left, SBB const &right);

//Complexity: O(n*n).
RACEPAIR NaiveDRCheck(SBB const &left, SBB const &right);

#endif
